#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pylenium.element import Element, Elements
from dragon.should import DraElementShould, DraElementsShould
from pathlib import Path
from dragon.locatordetail import LocatorDetail
import allure

class DraElement:
    def __init__(self, element: Element, ld:LocatorDetail ,pyd):
        from dragon.drapylenium import DraPylenium
        self._ld = ld
        self._pyd:DraPylenium=pyd
        self._element = element
        self.webelement = self._element.webelement

    def find(self, ld:LocatorDetail, timeout: int = None):
        '''查找符合locator的第一个元素'''
        if ld.type == 'css':
            element = self._element.get(ld.locator, timeout)
        elif ld.type == 'xpath':
            element = self._element.getx(ld.locator, timeout)
        elif ld.type == 'text':
            element = self._element.contains(ld.locator, timeout)
        else:
            raise ValueError('元素type必须是`css`、`xpath`、`text`其中之一')
        return DraElement(element, ld,self._pyd)

    def finds(self, ld: LocatorDetail, timeout: int = None):
        '''查找符合locator的所有元素'''
        if ld.type == 'css':
            elements= self._element.find(ld.locator, timeout)
        elif ld.type == 'xpath':
            elements= self._element.findx(ld.locator, timeout)
        else:
            raise Exception('元素查找方法错误')
        return DraElements(elements,ld,self._pyd)

    def check(self,allow_selected=False):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并勾选'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.check(allow_selected)
        return self

    def uncheck(self,allow_selected=False):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并取消勾选'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.uncheck(allow_selected)
        return self

    def deselect(self,value):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并取消选中'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.deselect(value)
        return self

    def clear(self):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并清空输入'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.clear()
        return self

    def type(self, text):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并输入【{text}】'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.type(text)
        return self

    def submit(self):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并提交'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.submit()
        return self

    def enter(self):
        self._pyd.sleep(1)
        stepText = f'步骤：定位到【{self._ld.name}】>> 并点击回车'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.type(self._pyd._py.Keys)
        return self

    def click(self,force=False):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并点击'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.click(force)
        return self._pyd

    def focus(self):
        '''定位到元素并聚焦'''
        stepText = f'步骤：定位到【{self._ld.name}】>> 并聚焦'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.focus()
        return self

    def hover(self):
        '''定位到元素并悬停'''
        stepText = f'步骤：定位到【{self._ld.name}】>> 并悬停'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.hover()
        return self._pyd

    def right_click(self):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并右击'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.right_click()
        return self._pyd

    def double_click(self):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并双击'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.double_click()
        return self._pyd

    def scroll_into_view(self):
        '''查找元素并滚动到元素可见'''
        stepText = f'步骤：定位到【{self._ld.name}】>> 并滚动到可见'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.scroll_into_view()
        return self

    def drag_to(self, ld: LocatorDetail):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并拖拽到【{ld.name}】'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.drag_to(ld.locator)
        return self

    def highlight(self, effect_time=1, color="red", border=5):
        self._element.highlight(effect_time,color,border)
        return self

    def drag_to_element(self, to_draElement):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并拖拽到【{to_draElement._ld.name}】'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.drag_to_element(to_draElement._element)
        return self

    def select_by_index(self,index: int):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并选中`index`为【{index}】的选项'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.select_by_index(index)
        return self

    def select_by_text(self,text: str):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并选中`text`为【{text}】的选项'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.select_by_text(text)
        return self

    def select_by_value(self,value: str):
        stepText = f'步骤：定位到【{self._ld.name}】>> 并选中`value`属性为【{value}】的选项'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.select_by_value(value)
        return self

    def upload(self, filepath:str|Path):
        '''上传文件，要绝对路径'''
        stepText = f'步骤：定位到【{self._ld.name}】>> 上传文件【{filepath}】'
        with allure.step(stepText):
            self._pyd.log.info(stepText)
            self._element.upload(filepath)
        return self

    def screenshot(self, filename: str):
        '''元素截图'''
        self._element.screenshot(filename)

    def get_attribute(self, attribute: str):
        '''获取元素指定属性值'''
        return self._element.get_attribute(attribute)

    def get_css_value(self,property_name: str):
        return self._element.css_value(property_name)

    def get_property(self,prop: str):
        return self._element.get_property(prop)

    @property
    def tag_name(self):
        return self._element.tag_name()

    @property
    def text(self):
        '''获取元素文本'''
        # self._pyd.log.info(f'获取【{self._ld.name}】的文本')
        return self._element.text()

    @property
    def location(self):
        '''元素左上角相对于父级元素的位置'''
        return self._element.webelement.location

    def is_checked(self) -> bool:
        '''检查checkbox是否被选中'''
        return self._element.is_checked()

    def is_displayed(self) -> bool:
        '''检查元素是否可见'''
        return self._element.is_displayed()

    def is_enabled(self) -> bool:
        '''检查元素是否可用'''
        return self._element.is_enabled()

    def is_selected(self):
        '''检查option是否选中'''
        return self._element.is_enabled()

    def should(self, timeout: int = 10, ignored_exceptions: list = None):
        '返回元素断言对象'
        return DraElementShould(self._element.should(timeout,ignored_exceptions),self)

class DraElements:
    def __init__(self, elements: Elements, ld: LocatorDetail,pyd):
        from dragon.drapylenium import DraPylenium
        self._ld = ld
        self._pyd:DraPylenium=pyd
        self._elements = elements

    @property
    def first(self) -> DraElement:
        element = self._elements.first()
        ld=LocatorDetail(self._ld.locator,'第1个'+self._ld.name,self._ld.type)
        return DraElement(element, ld,self._pyd)

    @property
    def last(self) -> DraElement:
        element = self._elements.last()
        ld = LocatorDetail(self._ld.locator, '最后1个' + self._ld.name, self._ld.type)
        return DraElement(element, ld,self._pyd)

    def index(self,index:int):
        element=self._elements[index]
        if index>=0:
            name=f'第{index+1}个'+self._ld.name
        else:
            name= f'倒数第{-index}个' + self._ld.name
        ld = LocatorDetail(self._ld.locator, name, self._ld.type)
        return DraElement(element, ld, self._pyd)

    @property
    def length(self) -> int:
        return self._elements.length()

    def is_empty(self) -> bool:
        return self._elements.is_empty()

    def are_checked(self) -> bool:
        return self._elements.are_checked()

    def check(self, allow_selected=False):
       self._elements.check(allow_selected)
       return self

    def uncheck(self, allow_deselected=False):
        self._elements.uncheck(allow_deselected)
        return self

    def should(self, timeout: int = 10, ignored_exceptions: list = None):
        return DraElementsShould(self._elements.should(timeout,ignored_exceptions), self)
